<html>
 <head>
  <link rel="stylesheet" type="text/css" href="..//core/foam.css" />
  <script language="javascript" src="../core/bootFOAM.js"></script>
  <script language="javascript" src="dragon.js"></script>
  <title>FOAM DOM Objects</title>
  <style>
    h3 {color: #444;}
    .code {width:900px; white-space: pre; border: 1px solid; padding: 5px; font-family: monospace;}
    .output {width:900px; white-space: pre; border: 1px solid; padding: 5px; color: blue;}
    .error {border: 2px solid red;}
    .description { margin-left: 20px; font-size: 115%; }
  </style>
 </head>

 <body>

<script language="javascript">
FOAModel({
  name: 'DemoView',
  extendsModel: 'DetailView',
  templates: [ { name: 'toHTML' } ]
});
</script>

<!--
<foam model="Model" name="DemoView" extendsModel="DetailView">
  <templates>
     <template name="toHTML"><code>
       <h2>$$name{mode:'read-only'}<h2>
       <div class="code">$$code{mode:'read-only'}</div>
       <div class="results">$$results</div>
     </code></template>
  </templates>
</foam>
-->

<foam model="UnitTest" onInit="this.test()" view="DemoView">
  <name>By-Name Value binding</name>
  <description>Demonstrate the binding of $ values.</description>
  <code>
    FOAModel({name: 'Test', properties: [ { name: 'x' } ]});
    var t1 = Test.create({x:1});
    var t2 = Test.create({x:2});

    t1.x$ = t2.x$;
    log([t1.x, t2.x]);

    t1.x = 3;
    log([t1.x, t2.x]);

    t2.x = 4;
    log([t1.x, t2.x]);

    var t3 = Test.create({x$: t1.x$});
    log([t1.x, t2.x, t3.x]);
    
    t3.x = 5;
    log([t1.x, t2.x, t3.x]);
  </code>
</foam>

<foam model="UnitTest" onInit="this.test()" view="DemoView">
  <name>Context Examples</name>
  <code>
    X.a = 42;
    log(X.a);
    var Y = X.sub({a:1,b:2}, 'Y');
    log(Y);
    log(Y.a);
    Mouse.create();
    var m1 = Mouse.create();
    var m2 = Y.Mouse.create();
    log('m2.X ', m2.X);
    log('m1.X ', m1.X);
    log(m2.X.a);
    var m3 = m2.X.Mouse.create();
    log(m3.X);
    log(m3.X.a);
  </code>
  <tests>
    <foam model="UnitTest" name="SubTest1"><code>
    log('sub test 1, part 1');
    log('sub test 1, part 2');
    </code></foam>
    <foam model="UnitTest" name="SubTest2"><code>
    log('sub test 2');
    </code></foam>
  </tests>
</foam>

<foam model="UnitTest" onInit="this.test()" view="DemoView">
  <name>A UnitTest embedded in DOM</name>
  <code>
    log('Here I am.');
    log('And here.');
  </code>
  <tests>
    <foam model="UnitTest" name="SubTest1"><code>
    log('sub test 1, part 1');
    log('sub test 1, part 2');
    </code></foam>
    <foam model="UnitTest" name="SubTest2"><code>
    log('sub test 2');
    </code></foam>
  </tests>
</foam>

<foam model="UnitTest" onInit="this.test()" view="DemoView">
  <name>A failed Test</name>
  <code>
    fail("Something's wrong.");
  </code>
</foam>

<foam model="UnitTest" onInit="this.test()" view="DemoView">
  <name>DAO Tests</name>
  <description>Define the Model (like a schema) and create a DAO.</description>
  <code>
    Person = FOAM({
      model_: 'Model',
      name: 'Person',
      properties: [
        { name: 'id' },
        { name: 'name' },
        { name: 'sex', defaultValue: 'M' },
        { model_: 'IntegerProperty', name: 'age' }
      ]
    });

    dao = MDAO.create({model: Person})
      .addIndex(Person.NAME)
      .addIndex(Person.SEX, Person.AGE);

    log(dao);
</code>
  <tests>
    <foam model="UnitTest" name="SubTest1">
      <description>Add some sample data and select ot a 'sink'.</description>
      <code>
        dao.put(Person.create({id:'1', name:'John',  age:21}));
        dao.put(Person.create({id:'2', name:'Dave',  age:20}));
        dao.put(Person.create({id:'3', name:'Steve', age:19}));
        dao.put(Person.create({id:'4', name:'Andy',  age:18}));

        dao.select({put: function(p) { log('person: ', p.name); }});
    </code></foam>
    <foam model="UnitTest" name="SubTest2">
      <description>Select directly to an Array.</description>
      <code>
        var a = [];
        dao.select(a);
        jlog(a);
    </code></foam>
  </tests>
</foam>

<foam model="UnitTest" onInit="this.test()" view="DemoView">
  <name>aFunc Tests</name>
  <description>Test FOAM's Asynchronous-Functions (aFunc's).</description>
  <code>
    f1 = function(ret) { console.log('f1() called.'); ret(1); };
    f2 = function(ret, a) { console.log('f2() called.'); ret(a,2); };
    aprint = function(ret) { console.log(argsToArray(arguments).slice(1).join(', ')); ret(); };
  </code>
  <tests>


    <foam model="UnitTest" name="test1"><async>true</async><code>aprint.ao(f2.ao(f1))(ret);</code></foam>
    <foam model="UnitTest" name="test2"><async>true</async><code>f1.aseq(f2.aseq(aprint))(ret);</code></foam>
    <foam model="UnitTest" name="test3"><async>true</async><code>f1.aseq(aprint)(ret);</code></foam>
    <foam model="UnitTest" name="test4"><async>true</async><code>ao(aprint,f2,f1)(ret);</code></foam>
    <foam model="UnitTest" name="test5"><async>true</async><code>aseq(f1, aprint)(ret);</code></foam>
    <foam model="UnitTest" name="test6"><async>true</async><code>aseq(f1,f2,aprint)(ret);</code></foam>
    <foam model="UnitTest" name="amemo">
      <async>true</async>
      <description>Test that amemo() only executes its delegate once.</description>
      <code>
        m = amemo(function(ret) { console.log('Should only see this once.'); ret(1); });
        apar(m, m, m).aseq(aprint)(ret);
      </code>
    </foam>
    <foam model="UnitTest" name="test7">
      <async>true</async>
      <code>
        aseq(
          function(ret) { console.log('fB'); ret(1); },
          function(ret) { console.log('fC'); ret(2); },
          aprint
        )(ret);
      </code>
    </foam>
    <foam model="UnitTest" name="test8">
      <async>true</async>
      <code>
        apar(
          function(ret, a) { console.log('fB'); ret(1); },
          function(ret, a) { console.log('fC'); ret(2); }
        )(aprint.aseq(ret));
      </code>
    </foam>
    <!--
    <foam model="UnitTest" name="test9">
      <async>true</async>
      <code>
        aseq(
          arepeatpar(5, aseq(ayield(), function(ret, a, b) { console.log('a', a); ret(1); })),
          ayield(),
          arepeatpar(5, function(ret, a, b) { console.log('b', a); ret(1); }),
          ayield()
        )(ret);
      </code>
    </foam>
    -->
    <foam model="UnitTest" name="arepeat 1">
      <async>true</async>
      <code>
        arepeat(5, f1)(ret);
      </code>
    </foam>
    <foam model="UnitTest" name="arepeat 2">
      <async>true</async>
      <code>
        arepeat(5, function(ret, a, b) { console.log(a); ret(1); }).aseq(aprint)(ret);
      </code>
    </foam>
    <foam model="UnitTest" name="arepeat 3">
      <async>true</async>
      <code>
        aseq(
          arepeat(5, function(ret, a, b) { console.log(a); ret(1); }),
          aprint)(ret);
      </code>
    </foam>
    <foam model="UnitTest" name="test11">
      <async>true</async>
      <code>
        aseq(
          function(ret) { console.log('fA'); ret(1); },
          apar(
            function(ret, a) { console.log('fB', a); ret(1); },
            function(ret, a) { console.log('fC', a); ret(2); }
          ),
          aprint
        )(ret);
      </code>
    </foam>
    <foam model="UnitTest" name="anop">
      <async>true</async>
      <code>log('anop'); aseq(alog('before'), anop, alog('after'))(ret);</code>
    </foam>
    <foam model="UnitTest" name="abind">
      <async>true</async>
      <code>
          var boo = function() { log('boo'); }
          boo();
          boo.abind(null)(ret);
      </code>
    </foam>
    <foam model="UnitTest" name="alog">
      <async>true</async>
      <code>log('alog'); alog('a message')(ret);</code>
    </foam>
    <!--
    <foam model="UnitTest" name="cooperative multithreading">
      <async>true</async>
      <code>
          apar(
            arepeat(10, aseq(alog('A'), ayield())),
            arepeat(10, aseq(alog('B'), ayield()))
          ))(ret);
      </code>
    </foam>
    -->
    <!--
    <foam model="UnitTest" name="atimeout">
      <async>true</async>
      <description>What should be the semantics of atimeout()?  Should it still ret()?</description>
      <code>
        aseq(
          aseq(
            alog('starting'),
            atimeout(1000, asleep(500), alog('too slow')),
            alog('on time')
          ),
          aseq(
            alog('starting'),
            atimeout(1000, asleep(1500), alog('too slow')),
            alog('on time')
          ))(ret);
      </code>
    </foam>
    -->
    <foam id="test" model="UnitTest" name="asleep2">
      <async>true</async>
      <code>
        log('**********');
        console.log('************** Beginning asleep2');
        aseq(alog('before'), asleep(1000), alog('after'), asleep(1000), alog('much after'))(ret);
//        log('after it all');
      </code>
    </foam>
    <foam model="UnitTest" name="asleep2">
      <async>true</async>
      <code>
        log('at the start');
        aseq(asleep(1000), alog('a message'))(ret);
      </code>
    </foam>
    <!--
    <foam model="UnitTest" name="ayield">
      <async>true</async>
      <code>
        aseq(ayield, alog('And then this second.'))(ret);
        log('This should print first.');
      </code>
    </foam>
    -->
    <foam model="UnitTest" name="Future Function">
      <async>true</async>
      <code>
        log('start');
  var functionFuture = afuture();
  var fn = futurefn(functionFuture);

  fn("hello");
  setTimeout(function() { fn(" world!"); ret(); }, 1000);
  setTimeout(function() { functionFuture.set(log); }, 100);
      </code>
    </foam>
    <foam model="UnitTest" name="asynchronized">
      <code>
        tlock = {};

        f1 = aseq(
          alog('f1 start'),
          asleep(2000),
          alog('f1 end')
        );
      </code>
      <tests>
        <foam model="UnitTest" name="Without Synchronization">
          <async>true</async>
          <code>
            apar(
              f1,
              f1,
              f1
            )(ret);
          </code>
        </foam>
        <foam model="UnitTest" name="With Synchronization">
          <async>true</async>
          <code>
            var f2 = aseq(asynchronized(atime('f2', f1), tlock), alog('END'));

            apar(
              f2,
              f2,
              f2
            )(ret);
          </code>
        </foam>
      </tests>
    </foam>
  </tests>
</foam>

 </body>
</html>
